package com.zshan.clinic.admin.service.medical;


import com.fasterxml.jackson.core.type.TypeReference;
import com.zshan.clinic.admin.entity.dto.ClinicMedicalDTO;
import com.zshan.clinic.admin.entity.medical.DrugRxItem;
import com.zshan.clinic.admin.entity.medical.FieldRxItem;
import com.zshan.clinic.admin.entity.medical.PatientMedicalField;
import com.zshan.clinic.admin.entity.medical.exam.ExamDetail;
import com.zshan.clinic.admin.entity.medical.field.MedicalFieldDetail;
import com.zshan.clinic.admin.entity.medical.rx.RxDrug;
import com.zshan.clinic.admin.entity.medical.rx.RxExt;
import com.zshan.clinic.admin.entity.medical.rx.RxInfusion;
import com.zshan.clinic.admin.entity.medical.rx.RxTcm;
import com.zshan.clinic.admin.entity.medical.rx.base.*;
import com.zshan.clinic.admin.entity.vo.*;
import com.zshan.clinic.admin.entity.vo.print.ClinicExamPrintVo;
import com.zshan.clinic.admin.entity.vo.print.ClinicMedicalPrintVo;
import com.zshan.clinic.admin.entity.vo.print.ClinicRxPrintVo;
import com.zshan.clinic.admin.entity.vo.print.exam.ExamPrintDetail;
import com.zshan.clinic.admin.entity.vo.print.medical.MedicalFieldPrintDetail;
import com.zshan.clinic.admin.entity.vo.print.rx.RxPrintBase;
import com.zshan.clinic.admin.entity.vo.print.rx.drug.RxDrugPrint;
import com.zshan.clinic.admin.entity.vo.print.rx.drug.RxDrugPrintDetail;
import com.zshan.clinic.admin.entity.vo.print.rx.ext.RxExtPrint;
import com.zshan.clinic.admin.entity.vo.print.rx.ext.RxExtPrintInfo;
import com.zshan.clinic.admin.entity.vo.print.rx.infussion.RxInfusionGroupPrint;
import com.zshan.clinic.admin.entity.vo.print.rx.infussion.RxInfusionGroupPrintDetail;
import com.zshan.clinic.admin.entity.vo.print.rx.infussion.RxInfusionPrint;
import com.zshan.clinic.admin.entity.vo.print.rx.tcm.RxTcmPrint;
import com.zshan.clinic.admin.entity.vo.print.rx.tcm.RxTcmPrintDetail;
import com.zshan.clinic.admin.entity.vo.print.rx.tcm.RxTcmPrintInfo;
import com.zshan.clinic.admin.mapper.medical.SpecClinicMedicalMapper;
import com.zshan.clinic.admin.service.MedicalValidateService;
import com.zshan.clinic.admin.service.clinic.ClinicEmpService;
import com.zshan.clinic.admin.service.config.MedicalFieldService;
import com.zshan.clinic.admin.service.config.PrintConfigService;
import com.zshan.clinic.admin.service.patient.ClinicPatientService;
import com.zshan.clinic.admin.task.AsyncTaskService;
import com.zshan.clinic.common.constant.CommonConstant;
import com.zshan.clinic.common.constant.MedicalConstant;
import com.zshan.clinic.common.enums.*;
import com.zshan.clinic.common.exception.BusinessFailException;
import com.zshan.clinic.common.util.date.DateTimeUtils;
import com.zshan.clinic.common.util.json.JsonUtil;
import com.zshan.clinic.common.util.page.PageInfo;
import com.zshan.clinic.common.util.page.PageUtils;
import com.zshan.clinic.common.util.string.StringUtil;
import com.zshan.clinic.database.dao.ClinicMedicalExamMapper;
import com.zshan.clinic.database.dao.ClinicMedicalFieldMapper;
import com.zshan.clinic.database.dao.ClinicMedicalMapper;
import com.zshan.clinic.database.dao.ClinicMedicalRxMapper;
import com.zshan.clinic.database.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 门诊
 */
@Service
@Slf4j
public class ClinicMedicalService extends MedicalValidateService {

    @Autowired
    private ClinicMedicalMapper clinicMedicalMapper;

    @Autowired
    private ClinicMedicalFieldMapper clinicMedicalFieldMapper;

    @Autowired
    private ClinicMedicalExamMapper clinicMedicalExamMapper;

    @Autowired
    private ClinicMedicalRxMapper clinicMedicalRxMapper;

    @Autowired
    @Lazy
    private ClinicRegisterService registerService;

    @Autowired
    private MedicalFieldService medicalFieldService;

    @Autowired
    private ClinicPatientService patientService;

    @Autowired
    private SpecClinicMedicalMapper specClinicMedicalMapper;

    @Autowired
    @Lazy
    private ChargeOrderService chargeOrderService;

    @Autowired
    @Lazy
    private ClinicQueueService clinicQueueService;

    @Autowired
    private ClinicFollowupService clinicFollowupService;

    @Autowired
    @Lazy
    private AsyncTaskService asyncTaskService;

    @Autowired
    private PrintConfigService printConfigService;

    @Autowired
    private ClinicEmpService clinicEmpService;


    /**
     * 根据诊号获取门诊数据
     * @param visitNo
     * @return
     */
    public ClinicMedical getMedicalByVisitNo(String visitNo) {
        ClinicMedicalExample example = new ClinicMedicalExample();
        ClinicMedicalExample.Criteria criteria = example.createCriteria();
        criteria.andVisitNoEqualTo(visitNo);
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        List<ClinicMedical> medicalList = clinicMedicalMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(medicalList)){
            return null;
        }
        return medicalList.get(0);
    }

    /**
     * 打印处方
     * @param clinicId
     * @param medicalId
     * @param isAll 是否打印全部处方
     * @param printBy
     * @return
     */
    public ClinicRxPrintVo getClinicRxPrint(Long clinicId, Long medicalId, String isAll,String printBy) {
        ClinicPrintConfigVo clinicPrintConfigVo = printConfigService.getConfigByCategoryAndType(clinicId,PrintCategoryEnum.DOCUMENT.getValue(),PrintTypeEnum.getRxList());
        if(clinicPrintConfigVo == null){
            throw new BusinessFailException("打印抬头未设置，请联系管理员处理！");
        }
        ClinicMedicalDetailVo clinicMedicalDetailVo = getMedicalDetail(clinicId,medicalId);
        if(clinicMedicalDetailVo == null){
            throw new BusinessFailException("病历不存在");
        }
        List<RxBase> rxList = clinicMedicalDetailVo.getRxList();
        if(CollectionUtils.isEmpty(rxList)){
            return null;
        }
        ClinicRxPrintVo clinicRxPrintVo = new ClinicRxPrintVo();
        //--------------打印的头部信息----------------
        clinicRxPrintVo.setPatientName(clinicMedicalDetailVo.getPatientName());
        clinicRxPrintVo.setPatientGender(clinicMedicalDetailVo.getPatientGender());
        clinicRxPrintVo.setAgeYear(clinicMedicalDetailVo.getAgeYear());
        clinicRxPrintVo.setAgeMonth(clinicMedicalDetailVo.getAgeMonth());
        clinicRxPrintVo.setPatientPhone(clinicMedicalDetailVo.getPatientPhone());
        clinicRxPrintVo.setVisitNo(clinicMedicalDetailVo.getVisitNo());
        clinicRxPrintVo.setVisitType(clinicMedicalDetailVo.getVisitType());
        clinicRxPrintVo.setRegType(clinicMedicalDetailVo.getRegType());
        clinicRxPrintVo.setDeptName(clinicMedicalDetailVo.getDeptName());
        List<MedicalFieldDetail> fieldList = clinicMedicalDetailVo.getFieldList();
        if(!CollectionUtils.isEmpty(fieldList)){
            fieldList.stream()
                    .filter(f -> MedicalConstant.ZHZD.equals(f.getFieldCode())) // 过滤出最终诊断
                    .findFirst()                                               // 取第一个匹配的
                    .ifPresent(f -> clinicRxPrintVo.setDiagnosis(f.getFieldValue()));
        }
        //获取签名信息
        List<StockDrugSignature> signatureList = drugProfileService.getSignatureList(clinicId,clinicMedicalDetailVo.getDoctorId(),getDrugIdListByRx(rxList));
        //将签名信息转换成map提高索引效率
        Map<Long, String> signatureMap = Optional.ofNullable(signatureList).orElse(Collections.emptyList())
                .stream()
                .collect(Collectors.toMap(
                        StockDrugSignature::getDrugId,
                        StockDrugSignature::getSignature,
                        (oldV, newV) -> newV  // 有重复 drugId 时，后者覆盖（与原逻辑一致）
                ));

        List<RxPrintBase> rxPrintList = new ArrayList<>();
        // 单次遍历
        for (RxBase rxBase : rxList) {
            if(YesOrNoEnum.YES.getValue().equals(isAll) || PayStatusEnum.ORDERED.getValue().equals(rxBase.getPayStatus())){
                // 根据 rxType 类型添加到对应的列表中
                if (RxTypeEnum.DRUG.getValue().equals(rxBase.getRxType())) {
                    RxDrugPrint rxDrugPrint = handleRxDrugPrint((RxDrug) rxBase,signatureMap);
                    if(rxDrugPrint != null){
                        rxDrugPrint.setRxName(rxBase.getRxName());
                        rxDrugPrint.setRxType(rxBase.getRxType());
                        rxPrintList.add(rxDrugPrint);
                    }
                } else if (RxTypeEnum.INFUSION.getValue().equals(rxBase.getRxType())) {
                    RxInfusionPrint rxInfusionPrint = handleRxInfusionPrint((RxInfusion) rxBase,signatureMap);
                    if(rxInfusionPrint != null){
                        rxInfusionPrint.setRxName(rxBase.getRxName());
                        rxInfusionPrint.setRxType(rxBase.getRxType());
                        rxPrintList.add(rxInfusionPrint);
                    }
                } else if (RxTypeEnum.EXT.getValue().equals(rxBase.getRxType())) {
                    RxExtPrint rxExtPrint = handleRxExtPrint((RxExt) rxBase);
                    if(rxExtPrint != null){
                        rxExtPrint.setRxName(rxBase.getRxName());
                        rxExtPrint.setRxType(rxBase.getRxType());
                        rxPrintList.add(rxExtPrint);
                    }
                } else if (RxTypeEnum.TCM.getValue().equals(rxBase.getRxType())) {
                    RxTcmPrint rxTcmPrint = handleRxTcmPrint((RxTcm) rxBase,signatureMap);
                    if(rxTcmPrint != null){
                        rxTcmPrint.setRxName(rxBase.getRxName());
                        rxTcmPrint.setRxType(rxBase.getRxType());
                        rxPrintList.add(rxTcmPrint);
                    }
                }
            }
        }
        clinicRxPrintVo.setRxList(rxPrintList);
        //-------------底部信息--------------
        clinicRxPrintVo.setDoctorName(clinicMedicalDetailVo.getDoctorName());
        ClinicEmpSignature clinicEmpSignature = clinicEmpService.getClinicEmpSignature(clinicId,clinicMedicalDetailVo.getDoctorId());
        if(clinicEmpSignature != null){
            //医生签名
            clinicRxPrintVo.setSignature(clinicEmpSignature.getSignature());
        }
        if(clinicMedicalDetailVo.getDiagnosisTime() != null){
            clinicRxPrintVo.setDiagnosisDate(DateTimeUtils.toLocalDate(clinicMedicalDetailVo.getDiagnosisTime()));
        }
        clinicRxPrintVo.setPrintBy(printBy);
        clinicRxPrintVo.setPrintTime(new Date());
        clinicRxPrintVo.setTitle(clinicPrintConfigVo.getTitle());
        clinicRxPrintVo.setAddress(clinicPrintConfigVo.getAddress());
        clinicRxPrintVo.setPhone(clinicPrintConfigVo.getPhone());
        return clinicRxPrintVo;
    }

    private RxExtPrint handleRxExtPrint(RxExt rxExt) {
        RxExtInfo rxExtInfo = rxExt.getExtInfo();
        if (rxExtInfo == null) {
            return null;
        }
        RxExtPrint rxExtPrint = new RxExtPrint();
        RxExtPrintInfo rxExtPrintInfo = new RxExtPrintInfo();
        BeanUtils.copyProperties(rxExtInfo, rxExtPrintInfo);
        rxExtPrint.setExtInfo(rxExtPrintInfo);
        return rxExtPrint;
    }

    private RxTcmPrint handleRxTcmPrint(RxTcm rxTcm,Map<Long, String> signatureMap) {
        RxTcmInfo rxTcmInfo = rxTcm.getTcmInfo();
        if (rxTcmInfo == null) {
            return null;
        }
        RxTcmPrint rxTcmPrint = new RxTcmPrint();
        RxTcmPrintInfo rxTcmPrintInfo = new RxTcmPrintInfo();
        BeanUtils.copyProperties(rxTcmInfo, rxTcmPrintInfo);
        List<RxTcmPrintDetail> rxTcmPrintDetailList = new ArrayList<>();
        List<RxTcmDetail> detailList = rxTcmInfo.getDetailList();
        if(CollectionUtils.isEmpty(detailList)){
            return null;
        }
        for(RxTcmDetail rxTcmDetail : detailList){
            RxTcmPrintDetail rxTcmPrintDetail = new RxTcmPrintDetail();
            BeanUtils.copyProperties(rxTcmDetail,rxTcmPrintDetail);
            if(StringUtil.isNotBlank(rxTcmPrintDetail.getDecotionMethod())){
                rxTcmPrintDetail.setDecotionMethod(DecotionMethodEnum.getText(rxTcmPrintDetail.getDecotionMethod()));
            }
            rxTcmPrintDetailList.add(rxTcmPrintDetail);
            if(!CollectionUtils.isEmpty(signatureMap)){
                rxTcmPrintDetail.setSignature(signatureMap.get(rxTcmDetail.getDrugId()));
            }
        }
        rxTcmPrintInfo.setDetailList(rxTcmPrintDetailList);
        rxTcmPrint.setTcmInfo(rxTcmPrintInfo);
        return rxTcmPrint;
    }

    public RxInfusionPrint handleRxInfusionPrint(RxInfusion rxInfusion,Map<Long, String> signatureMap) {
        List<RxInfusionGroup> groupList = rxInfusion.getGroupList();
        if (CollectionUtils.isEmpty(groupList)) {
            return null;
        }
        List<RxInfusionGroupPrint> rxInfusionGroupPrintList = new ArrayList<>();
        for (RxInfusionGroup rxGroup : groupList) {
            RxInfusionGroupPrint rxInfusionGroupPrint = new RxInfusionGroupPrint();
            BeanUtils.copyProperties(rxGroup, rxInfusionGroupPrint);
            List<RxInfusionGroupDetail> detailList = rxGroup.getDetailList();
            if (CollectionUtils.isEmpty(detailList)) {
                continue;
            }
            List<RxInfusionGroupPrintDetail> resultDetailList = new ArrayList<>();
            for (RxInfusionGroupDetail detail : detailList) {
                RxInfusionGroupPrintDetail rxInfusionGroupPrintDetail = new RxInfusionGroupPrintDetail();
                BeanUtils.copyProperties(detail, rxInfusionGroupPrintDetail);
                if(DrugCategoryEnum.PATENT_MEDICINE.getValue().equals(detail.getDrugCategory())){
                    rxInfusionGroupPrintDetail.setDrugName(detail.getDrugName()
                            +detail.getDrugDosage()+detail.getDrugDosageUnitText()+"*"
                            +detail.getMinPackQty()+detail.getMinPackUnitText()+"/"+detail.getPackUnitText());
                }else if (DrugCategoryEnum.CONSUMABLE.getValue().equals(detail.getDrugCategory())){
                    rxInfusionGroupPrintDetail.setDrugName(detail.getDrugName() + detail.getMinPackQty()+detail.getMinPackUnitText()+"/"+detail.getPackUnitText());
                }
                resultDetailList.add(rxInfusionGroupPrintDetail);
                if(!CollectionUtils.isEmpty(signatureMap)){
                    rxInfusionGroupPrintDetail.setSignature(signatureMap.get(detail.getDrugId()));
                }
            }
            rxInfusionGroupPrint.setDetailList(resultDetailList);
            rxInfusionGroupPrintList.add(rxInfusionGroupPrint);
        }
        RxInfusionPrint rxInfusionPrint = new RxInfusionPrint();
        rxInfusionPrint.setGroupList(rxInfusionGroupPrintList);
        return rxInfusionPrint;
    }

    public RxDrugPrint handleRxDrugPrint(RxDrug rxDrug,Map<Long, String> signatureMap) {
        List<RxDrugDetail> detailList = rxDrug.getDetailList();
        if(CollectionUtils.isEmpty(detailList)){
            return null;
        }
        RxDrugPrint rxDrugPrint = new RxDrugPrint();
        List<RxDrugPrintDetail> rxDrugPrintDetailList = new ArrayList<>();
        for (RxDrugDetail rxDrugDetail : detailList) {
            RxDrugPrintDetail rxDrugPrintDetail = new RxDrugPrintDetail();
            BeanUtils.copyProperties(rxDrugDetail, rxDrugPrintDetail);
            if(DrugCategoryEnum.PATENT_MEDICINE.getValue().equals(rxDrugDetail.getDrugCategory())){
                rxDrugPrintDetail.setDrugName(rxDrugDetail.getDrugName()
                        +rxDrugDetail.getDrugDosage()+rxDrugDetail.getDrugDosageUnitText()+"*"
                        +rxDrugDetail.getMinPackQty()+rxDrugDetail.getMinPackUnitText()+"/"+rxDrugDetail.getPackUnitText());
            }else if (DrugCategoryEnum.CONSUMABLE.getValue().equals(rxDrugDetail.getDrugCategory())){
                rxDrugPrintDetail.setDrugName(rxDrugDetail.getDrugName() + rxDrugDetail.getMinPackQty()+rxDrugDetail.getMinPackUnitText()+"/"+rxDrugDetail.getPackUnitText());
            }
            if(!CollectionUtils.isEmpty(signatureMap)){
                rxDrugPrintDetail.setSignature(signatureMap.get(rxDrugDetail.getDrugId()));
            }
            rxDrugPrintDetailList.add(rxDrugPrintDetail);
        }
        rxDrugPrint.setDetailList(rxDrugPrintDetailList);
        return rxDrugPrint;
    }

    /**
     * 打印检查单
     * @param clinicId
     * @param medicalId
     * @param isAll 是否打印全部检查单
     * @param printBy
     * @return
     */
    public ClinicExamPrintVo getClinicExamPrint(Long clinicId, Long medicalId, String isAll,String printBy) {
        ClinicPrintConfigVo clinicPrintConfig = printConfigService.getConfigByCategoryAndType(clinicId,PrintCategoryEnum.DOCUMENT.getValue(),Collections.singletonList(PrintTypeEnum.EXAM_REQUEST.getValue()));
        if(clinicPrintConfig == null){
            throw new BusinessFailException("打印抬头未设置，请联系管理员处理！");
        }
        ClinicMedicalDetailVo clinicMedicalDetailVo = getMedicalDetail(clinicId,medicalId);
        if(clinicMedicalDetailVo == null){
            throw new BusinessFailException("病历不存在");
        }
        ClinicExamPrintVo clinicExamPrintVo = new ClinicExamPrintVo();
        //--------------打印的头部信息----------------
        clinicExamPrintVo.setPatientName(clinicMedicalDetailVo.getPatientName());
        clinicExamPrintVo.setPatientGender(clinicMedicalDetailVo.getPatientGender());
        clinicExamPrintVo.setAgeYear(clinicMedicalDetailVo.getAgeYear());
        clinicExamPrintVo.setAgeMonth(clinicMedicalDetailVo.getAgeMonth());
        clinicExamPrintVo.setPatientPhone(clinicMedicalDetailVo.getPatientPhone());
        clinicExamPrintVo.setVisitNo(clinicMedicalDetailVo.getVisitNo());
        clinicExamPrintVo.setVisitType(clinicMedicalDetailVo.getVisitType());
        clinicExamPrintVo.setRegType(clinicMedicalDetailVo.getRegType());
        clinicExamPrintVo.setDeptName(clinicMedicalDetailVo.getDeptName());
        List<MedicalFieldDetail> fieldList = clinicMedicalDetailVo.getFieldList();
        if(!CollectionUtils.isEmpty(fieldList)){
            fieldList.stream()
                    .filter(f -> MedicalConstant.CBZD.equals(f.getFieldCode())) // 过滤出初步诊断
                    .findFirst()                                               // 取第一个匹配的
                    .ifPresent(f -> clinicExamPrintVo.setPreliminaryDiagnosis(f.getFieldValue()));
        }
        List<ExamPrintDetail> examPrintDetailList =
                Optional.ofNullable(clinicMedicalDetailVo.getExamList()).orElse(Collections.emptyList())
                        .stream()
                        // isAll=YES 则不过滤；否则只要已下单(ORDERED)的
                        .filter(e -> YesOrNoEnum.YES.getValue().equals(isAll)
                                || PayStatusEnum.ORDERED.getValue().equals(e.getPayStatus()))
                        .map(e -> {
                            ExamPrintDetail d = new ExamPrintDetail();
                            BeanUtils.copyProperties(e, d);
                            return d;
                        })
                        .collect(Collectors.toList());
        clinicExamPrintVo.setExamList(examPrintDetailList);
        //-------------底部信息--------------
        clinicExamPrintVo.setDoctorName(clinicMedicalDetailVo.getDoctorName());
        ClinicEmpSignature clinicEmpSignature = clinicEmpService.getClinicEmpSignature(clinicId,clinicMedicalDetailVo.getDoctorId());
        if(clinicEmpSignature != null){
            //医生签名
            clinicExamPrintVo.setSignature(clinicEmpSignature.getSignature());
        }
        clinicExamPrintVo.setApplyDate(clinicMedicalDetailVo.getVisitDate());
        clinicExamPrintVo.setPrintBy(printBy);
        clinicExamPrintVo.setPrintTime(new Date());
        clinicExamPrintVo.setTitle(clinicPrintConfig.getTitle());
        clinicExamPrintVo.setAddress(clinicPrintConfig.getAddress());
        clinicExamPrintVo.setPhone(clinicPrintConfig.getPhone());
        return clinicExamPrintVo;
    }

    /**
     * 打印病历单
     * @param clinicId
     * @param medicalId
     * @return
     */
    public ClinicMedicalPrintVo getClinicMedicalPrint(Long clinicId, Long medicalId,String printBy) {
        ClinicPrintConfigVo clinicPrintConfig = printConfigService.getConfigByCategoryAndType(clinicId,PrintCategoryEnum.DOCUMENT.getValue(),Collections.singletonList(PrintTypeEnum.MEDICAL_RECORD.getValue()));
        if(clinicPrintConfig == null){
            throw new BusinessFailException("打印抬头未设置，请联系管理员处理！");
        }
        ClinicMedicalDetailVo clinicMedicalDetailVo = getMedicalDetail(clinicId,medicalId);
        if(clinicMedicalDetailVo == null){
            throw new BusinessFailException("病历不存在");
        }
//        if(StringUtil.isBlank(clinicMedicalDetailVo.getDiagnosis())){
//            log.info(">>>>>>>病历还没完成，不能打印>>>>>>>>>>>>>>>>>>>>>>>>");
//            return null;
//        }
        ClinicMedicalPrintVo clinicMedicalPrintVo = new ClinicMedicalPrintVo();
        //--------------打印的头部信息----------------
        clinicMedicalPrintVo.setPatientName(clinicMedicalDetailVo.getPatientName());
        clinicMedicalPrintVo.setPatientGender(clinicMedicalDetailVo.getPatientGender());
        clinicMedicalPrintVo.setAgeYear(clinicMedicalDetailVo.getAgeYear());
        clinicMedicalPrintVo.setAgeMonth(clinicMedicalDetailVo.getAgeMonth());
        clinicMedicalPrintVo.setPatientPhone(clinicMedicalDetailVo.getPatientPhone());
        clinicMedicalPrintVo.setVisitNo(clinicMedicalDetailVo.getVisitNo());
        clinicMedicalPrintVo.setVisitType(clinicMedicalDetailVo.getVisitType());
        clinicMedicalPrintVo.setRegType(clinicMedicalDetailVo.getRegType());
        clinicMedicalPrintVo.setDeptName(clinicMedicalDetailVo.getDeptName());
        //打印的病历信息 中部内容
        clinicMedicalPrintVo.setFieldList(
                clinicMedicalDetailVo.getFieldList()
                        .stream()
                        .filter(f -> StringUtil.isNotBlank(f.getFieldValue())) // 过滤掉无值项
                        .map(f -> {
                            MedicalFieldPrintDetail detail = new MedicalFieldPrintDetail();
                            detail.setFieldName(f.getFieldName());
                            detail.setFieldValue(f.getFieldValue());
                            return detail;
                        })
                        .collect(Collectors.toList())
        );
        clinicMedicalPrintVo.setDoctorAdvice(clinicMedicalDetailVo.getDoctorAdvice());
        //-------------底部信息--------------
        clinicMedicalPrintVo.setDoctorName(clinicMedicalDetailVo.getDoctorName());
        ClinicEmpSignature clinicEmpSignature = clinicEmpService.getClinicEmpSignature(clinicId,clinicMedicalDetailVo.getDoctorId());
        if(clinicEmpSignature != null){
            //医生签名
            clinicMedicalPrintVo.setSignature(clinicEmpSignature.getSignature());
        }
        if(clinicMedicalDetailVo.getDiagnosisTime() != null){
            clinicMedicalPrintVo.setDiagnosisDate( DateTimeUtils.toLocalDate(clinicMedicalDetailVo.getDiagnosisTime()));
        }
        clinicMedicalPrintVo.setPrintBy(printBy);
        clinicMedicalPrintVo.setPrintTime(new Date());
        clinicMedicalPrintVo.setTitle(clinicPrintConfig.getTitle());
        clinicMedicalPrintVo.setAddress(clinicPrintConfig.getAddress());
        clinicMedicalPrintVo.setPhone(clinicPrintConfig.getPhone());
        return clinicMedicalPrintVo;
    }


    /**
     * 门诊校验
     * @param clinicMedicalDTO
     * @return
     */
    public List<String> verify(ClinicMedicalDTO clinicMedicalDTO){
        List<DrugRxItem> drugItemList = toDrugRxItems(clinicMedicalDTO.getRxList());
        if(CollectionUtils.isEmpty(drugItemList)){
            return Collections.EMPTY_LIST;
        }
        List<String> conflictList = new ArrayList<>();
        String drugItemsJson = JsonUtil.obj2Json(drugItemList);
        List<DrugConflictVo> drugConflictList = specClinicMedicalMapper.getConflictsByDrugIdList(clinicMedicalDTO.getClinicId(),drugItemsJson);
        if(!CollectionUtils.isEmpty(drugConflictList)){
            for(DrugConflictVo drugConflictVo : drugConflictList){
                String conflict = drugConflictVo.getRxName() +":"+"药品“"+drugConflictVo.getSrcName()+"”与药品“"+drugConflictVo.getConflictName()+"”存在药物相互作用，联合使用风险高，请谨慎评估。";
                conflictList.add(conflict);
            }
        }
        //病历字段
        List<MedicalFieldDetail> fieldList = clinicMedicalDTO.getFieldList();
        validateMedicalField(YesOrNoEnum.YES.getValue(),OperateTypeEnum.EDIT.getValue(),fieldList);
        Map<String, String> medicalFieldMap = fieldList.stream()
                .filter(d -> d.getFieldValue() != null).collect(Collectors.toMap(MedicalFieldDetail::getFieldCode, MedicalFieldDetail::getFieldValue, (a, b) -> b));
        //主诉
        String complaint = medicalFieldMap.get(MedicalConstant.ZS);
        List<FieldRxItem> fieldItemList = new ArrayList<>();
        if(StringUtil.isNotBlank(complaint)){
            fieldItemList.add(new FieldRxItem("主诉",complaint));
        }
        //既往史
        String medicalHistory = medicalFieldMap.get(MedicalConstant.JWS);
        if(StringUtil.isNotBlank(medicalHistory)){
            fieldItemList.add(new FieldRxItem("既往史",medicalHistory));
        }
        //过敏史
        String allergyHistory = medicalFieldMap.get(MedicalConstant.GMS);
        if(StringUtil.isNotBlank(allergyHistory)){
            fieldItemList.add(new FieldRxItem("过敏史",allergyHistory));
        }
        String fieldItemsJson = JsonUtil.obj2Json(fieldItemList);
        List<DrugConflictVo> fieldConflictList = specClinicMedicalMapper.getConflictsByField(clinicMedicalDTO.getClinicId(),drugItemsJson,fieldItemsJson);
        if(!CollectionUtils.isEmpty(fieldConflictList)){
            for(DrugConflictVo drugConflictVo : fieldConflictList){
                String conflict = drugConflictVo.getRxName() +":"+"药品“"+drugConflictVo.getSrcName()+"”与“"+drugConflictVo.getConflictName()+"”存在禁忌，请谨慎评估。";
                conflictList.add(conflict);
            }
        }
        return conflictList;
    }

    public List<DrugRxItem> toDrugRxItems(List<RxBase> rxList) {
        if (CollectionUtils.isEmpty(rxList)) {
            return Collections.emptyList();
        }

        return rxList.stream()
                .flatMap(rx -> extractDrugIdsPerRx(rx).stream()
                        .map(id -> new DrugRxItem(id, rx.getRxName())))
                .collect(Collectors.toList());
    }


    /** 按处方类型各自提取药品ID；对空集合/空对象已做 null 安全 */
    private List<Long> extractDrugIdsPerRx(RxBase rx) {
        if (rx == null || rx.getRxType() == null) {
            return Collections.emptyList();
        }
        if (RxTypeEnum.DRUG.getValue().equals(rx.getRxType())) {
            RxDrug d = (RxDrug) rx;
            return streamOf(d.getDetailList())
                    .map(RxDrugDetail::getDrugId)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
        }
        if (RxTypeEnum.INFUSION.getValue().equals(rx.getRxType())) {
            RxInfusion inf = (RxInfusion) rx;
            return streamOf(inf.getGroupList())
                    .flatMap(g -> streamOf(g.getDetailList()))
                    .map(RxInfusionGroupDetail::getDrugId)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
        }
        if (RxTypeEnum.TCM.getValue().equals(rx.getRxType())) {
            RxTcm t = (RxTcm) rx;
            return Optional.ofNullable(t.getTcmInfo())
                    .map(info -> streamOf(info.getDetailList())
                            .map(RxTcmDetail::getDrugId)
                            .filter(Objects::nonNull)
                            .collect(Collectors.toList()))
                    .orElseGet(Collections::emptyList);
        }
        // 未识别类型
        return Collections.emptyList();
    }

    /** 安全把可能为 null 的集合转成 Stream.empty() */
    private static <T> Stream<T> streamOf(Collection<T> c) {
        return c == null ? Stream.empty() : c.stream();
    }



    /**
     * 查询患者就诊记录
     * @param clinicId
     * @param patientId
     * @param visitDate
     * @param pageNo
     * @param pageSize
     * @return
     */
    public PageInfo<ClinicMedicalPatientVo> getPatientMedicalList(Long clinicId, Long patientId, LocalDate visitDate, Integer pageNo, Integer pageSize) {
        Long totalCount = specClinicMedicalMapper.getPatientMedicalCount(clinicId,patientId,visitDate);
        if(StringUtil.isBlank(totalCount)){
            return PageInfo.build();
        }
        List<ClinicMedicalPatientVo> medicalList = specClinicMedicalMapper.getPatientMedicalList(clinicId,patientId,visitDate,PageUtils.getOffset(pageNo,pageSize),pageSize);
        return new PageInfo<>(totalCount,medicalList);
    }

    /**
     * 查询诊所医生今日待诊数
     * @param clinicId
     * @param doctorId
     * @return
     */
    public Long getWaitingCount(Long clinicId, Long doctorId) {
        //医生助理也能看医生的数据
        List<Long> doctorList = new ArrayList<>();
        doctorList.add(doctorId);
        doctorList.addAll(projectFeeService.getDoctorListByAssistantId(doctorId));
        ClinicMedicalExample example = new ClinicMedicalExample();
        ClinicMedicalExample.Criteria criteria = example.createCriteria();
        criteria.andVisitDateEqualTo(LocalDate.now());
        criteria.andClinicIdEqualTo(clinicId);
        criteria.andDoctorIdIn(doctorList);
        criteria.andVisitStatusEqualTo(VisitStatusEnum.WAITING.getValue());
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        return clinicMedicalMapper.countByExample(example);
    }

    /**
     * 修改病历单
     * @param clinicMedicalDTO
     */
    @Transactional(rollbackFor = Exception.class)
    public Long editMedical(ClinicMedicalDTO clinicMedicalDTO){
//        if(!VisitStatusEnum.COMPLETED.getValue().equals(clinicMedicalDTO.getVisitStatus())){
//            throw new BusinessFailException("状态不允许");
//        }
        //修改病历
        updateMedicalDTO(clinicMedicalDTO);
        //完成诊断以后的操作
        Long medicalId = handleMedicalCompleted(clinicMedicalDTO);
        return  medicalId;
    }

    /**
     * 完成诊断
     * @param clinicMedicalDTO
     */
    @Transactional(rollbackFor = Exception.class)
    public Long completed(ClinicMedicalDTO clinicMedicalDTO){
        //保存病历单
        if(StringUtil.isBlank(clinicMedicalDTO.getMedicalId())){
            clinicMedicalDTO.setDoctorId(clinicMedicalDTO.getUpdateUserId());
            clinicMedicalDTO.setDoctorName(clinicMedicalDTO.getUpdateBy());
            clinicMedicalDTO.setCreateUserId(clinicMedicalDTO.getUpdateUserId());
            clinicMedicalDTO.setCreateBy(clinicMedicalDTO.getUpdateBy());
            addMedicalDTO(clinicMedicalDTO,ReqSourceEnum.WEB.getValue());
        }else {
            updateMedicalDTO(clinicMedicalDTO);
        }
        //修改病历的状态
        Long medicalId = handleMedicalCompleted(clinicMedicalDTO);
        return medicalId;
    }

    /**
     * TODO 完成诊断以后的操作，可以改为异步
     * @param clinicMedicalDTO
     */
    @Transactional(rollbackFor = Exception.class)
    public Long handleMedicalCompleted(ClinicMedicalDTO clinicMedicalDTO) {
        ClinicMedicalDetailVo clinicMedicalDetailVo = getMedicalDetail(
                clinicMedicalDTO.getClinicId(),
                clinicMedicalDTO.getMedicalId());
        PatientMedicalField patientMedicalField = getPatientMedicalField(clinicMedicalDetailVo.getFieldList());
        //回写主表的主诉和最后诊断
        if(patientMedicalField != null){
            clinicMedicalDetailVo.setComplaint(patientMedicalField.getComplaint());
            clinicMedicalDetailVo.setDiagnosis(patientMedicalField.getDiagnosis());
            clinicMedicalDetailVo.setDiagnosisTime(new Date());
        }
        //回写病历的主诉
        ClinicMedical clinicMedical = new ClinicMedical();
        clinicMedical.setMedicalId(clinicMedicalDetailVo.getMedicalId());
        if(!VisitStatusEnum.COMPLETED.getValue().equals(clinicMedicalDetailVo.getVisitStatus())){
            clinicMedical.setVisitStatus(VisitStatusEnum.COMPLETED.getValue());
        }
        clinicMedical.setComplaint(clinicMedicalDetailVo.getComplaint());
        clinicMedical.setDiagnosis(clinicMedicalDetailVo.getDiagnosis());
        clinicMedical.setDiagnosisTime(clinicMedicalDetailVo.getDiagnosisTime());
        clinicMedical.setUpdateUserId(clinicMedicalDTO.getUpdateUserId());
        clinicMedical.setUpdateBy(clinicMedicalDTO.getUpdateBy());
        updateMedical(clinicMedical);
        //完成诊断之后的第二步操作
        handleMedicalCompleted2(patientMedicalField,clinicMedicalDTO,clinicMedicalDetailVo);
        return clinicMedicalDetailVo.getMedicalId();
    }

    /**
     * 完成诊断之后的第二步操作
     * @param clinicMedicalDTO
     * @param clinicMedicalDetailVo
     */
    public void handleMedicalCompleted2(PatientMedicalField patientMedicalField,ClinicMedicalDTO clinicMedicalDTO,ClinicMedicalDetailVo clinicMedicalDetailVo) {
        //统计诊所今日营收
        StatClinicIncomeDaily statClinicIncomeDaily = new StatClinicIncomeDaily();
        statClinicIncomeDaily.setClinicId(clinicMedicalDTO.getClinicId());
        statClinicIncomeDaily.setMedicalCount(CommonConstant.DEFAULT_1);
        asyncTaskService.asyncSaveOrUpdateClinicIncome(statClinicIncomeDaily);
        //开具所有的单子
        chargeOrderService.createRxOrder(clinicMedicalDetailVo,clinicMedicalDTO.getUpdateUserId(),clinicMedicalDTO.getUpdateBy());
        //修改挂号单的状态已诊
        registerService.completed(clinicMedicalDetailVo.getRegisterId());
        //更新患者的信息
        ClinicPatient patientInfo = new ClinicPatient();
        patientInfo.setPatientId(clinicMedicalDetailVo.getPatientId());
        patientInfo.setPatientName(clinicMedicalDetailVo.getPatientName());
        patientInfo.setPatientGender(clinicMedicalDetailVo.getPatientGender());
        patientInfo.setPatientPhone(clinicMedicalDetailVo.getPatientPhone());
        patientInfo.setAgeYear(clinicMedicalDetailVo.getAgeYear());
        patientInfo.setAgeMonth(clinicMedicalDetailVo.getAgeMonth());
        patientInfo.setWeight(clinicMedicalDetailVo.getWeight());
        patientInfo.setSystolicBp(clinicMedicalDetailVo.getSystolicBp());
        patientInfo.setDiastolicBp(clinicMedicalDetailVo.getDiastolicBp());
        if(patientMedicalField != null){
            patientInfo.setMedicalHistory(patientMedicalField.getMedicalHistory());
            patientInfo.setAllergyHistory(patientMedicalField.getAllergyHistory());
        }
        patientInfo.setLastVisitDate(LocalDate.now());
        patientInfo.setUpdateUserId(clinicMedicalDTO.getUpdateUserId());
        patientInfo.setUpdateBy(clinicMedicalDTO.getUpdateBy());
        patientService.updatePatientLastVisit(patientInfo);
        //修改叫号表的状态
        clinicQueueService.treated(clinicMedicalDetailVo.getClinicId(),clinicMedicalDetailVo.getPatientId(),clinicMedicalDetailVo.getVisitNo());
        //判断是否需要随访增加随访记录
        if(YesOrNoEnum.YES.getValue().equals(clinicMedicalDetailVo.getIsFollowUp())){
            clinicFollowupService.addFollowup(clinicMedicalDetailVo,clinicMedicalDTO.getUpdateUserId(),clinicMedicalDTO.getUpdateBy());
        }
    }

    /**
     * 回写病人的过敏史
     * @param fieldList
     * @return
     */
    public PatientMedicalField getPatientMedicalField(List<MedicalFieldDetail> fieldList) {
        if(CollectionUtils.isEmpty(fieldList)){
            return null;
        }
        PatientMedicalField patientMedicalField = new PatientMedicalField();
        for(MedicalFieldDetail medicalFieldDetail : fieldList){
            if(MedicalConstant.ZS.equals(medicalFieldDetail.getFieldCode())){
                patientMedicalField.setComplaint(medicalFieldDetail.getFieldValue());
            }
            if(MedicalConstant.ZHZD.equals(medicalFieldDetail.getFieldCode())){
                patientMedicalField.setDiagnosis(medicalFieldDetail.getFieldValue());
            }
            if(MedicalConstant.JWS.equals(medicalFieldDetail.getFieldCode())){
                patientMedicalField.setMedicalHistory(medicalFieldDetail.getFieldValue());
            }
            if(MedicalConstant.GMS.equals(medicalFieldDetail.getFieldCode())){
                patientMedicalField.setAllergyHistory(medicalFieldDetail.getFieldValue());
            }
        }
        return patientMedicalField;
    }


    /**
     * 完成预诊
     * @param clinicMedicalDTO
     */
    @Transactional(rollbackFor = Exception.class)
    public Long confirmPre(ClinicMedicalDTO clinicMedicalDTO){
        //保存病历单
        Long medicalId = null;
        if(StringUtil.isBlank(clinicMedicalDTO.getMedicalId())){
            clinicMedicalDTO.setDoctorId(clinicMedicalDTO.getUpdateUserId());
            clinicMedicalDTO.setDoctorName(clinicMedicalDTO.getUpdateBy());
            clinicMedicalDTO.setCreateUserId(clinicMedicalDTO.getUpdateUserId());
            clinicMedicalDTO.setCreateBy(clinicMedicalDTO.getUpdateBy());
            medicalId = addMedicalDTO(clinicMedicalDTO,ReqSourceEnum.WEB.getValue());
        }else {
            medicalId = updateMedicalDTO(clinicMedicalDTO);
        }
        return medicalId;
    }

    /**
     * 查询门诊患者列表
     * @param clinicId
     * @param patientName
     * @param doctorId
     * @param visitDate
     * @return
     */
    public List<ClinicMedicalPageVo> getMedicalList(Long clinicId, String patientName, Long doctorId, LocalDate visitDate, Integer pageNo, Integer pageSize){
        //方便调试
//        if(visitDate == null){
//            visitDate = LocalDate.now();
//        }
        if(StringUtil.isNotBlank(patientName)){
            visitDate = null;
        }
        //医生助理也能看医生的数据
        List<Long> doctorList = new ArrayList<>();
        doctorList.add(doctorId);
        doctorList.addAll(projectFeeService.getDoctorListByAssistantId(doctorId));
        return specClinicMedicalMapper.getMedicalList(clinicId,patientName,doctorList,visitDate,PageUtils.getOffset(pageNo,pageSize),pageSize);
    }

    /**
     * 查询门诊患者就诊历史数
     * @param clinicId
     * @param patientId
     * @return
     */
    public Long getRecordCount(Long clinicId, Long patientId) {
        return specClinicMedicalMapper.getRecordCount(clinicId,patientId);
    }
    /**
     * 查询门诊患者就诊历史
     * @param clinicId
     * @param patientId
     * @return
     */
    public List<MedicalRecordVo> getRecordList(Long clinicId, Long patientId, Integer pageNo, Integer pageSize){
        return specClinicMedicalMapper.getRecordList(clinicId,patientId,PageUtils.getOffset(pageNo,pageSize),pageSize);
    }

    /**
     * 查询门诊患者病历详情
     * @param clinicId
     * @param medicalId
     * @return
     */
    public ClinicMedicalDetailVo getMedicalDetail(Long clinicId, Long medicalId){
        ClinicMedicalDetailVo clinicMedicalDetailVo = specClinicMedicalMapper.getMedicalDetail(clinicId,medicalId);
        if(clinicMedicalDetailVo == null){
            throw new BusinessFailException("病历不存在");
        }
        //获取病历字段
        List<MedicalFieldDetail> fieldList = JsonUtil.json2Obj(clinicMedicalDetailVo.getFieldListJson(),
                new TypeReference<List<MedicalFieldDetail>>() {});
        fieldList.sort(Comparator.comparingInt(MedicalFieldDetail::getSortNum));
        clinicMedicalDetailVo.setFieldList(fieldList);
        clinicMedicalDetailVo.setRxList(handleRxList(clinicMedicalDetailVo.getRxList()));
        /**
         * 如果处方是未支付的状态，需要用最新的价格
         */
        handleRxPrice(clinicId,clinicMedicalDetailVo.getRxList());
        return clinicMedicalDetailVo;
    }

    /**
     * 查询门诊患者病历详情
     * @param clinicId
     * @param visitNo
     * @param rxIdList
     * @return
     */
    public ClinicMedicalDetailVo getMedicalPayRxList(Long clinicId, String visitNo, List<Long> rxIdList){
        ClinicMedicalDetailVo clinicMedicalDetailVo = specClinicMedicalMapper.getMedicalPayRxList(clinicId,visitNo,rxIdList);
        if(clinicMedicalDetailVo == null){
            throw new BusinessFailException("病历不存在");
        }
        clinicMedicalDetailVo.setRxList(handleRxList(clinicMedicalDetailVo.getRxList()));
        return clinicMedicalDetailVo;
    }

    /**
     * 自动签到
     * @param register
     */
    @Transactional(rollbackFor = Exception.class)
    public void checkInAndMedical(ClinicRegister register) {
        log.info("自动签到添加门诊病历信息:{}",register);
        if(RegChannelEnum.OUTPATIENT.getValue().equals(register.getRegChannel())){
            //如果是在门诊直接看诊，就已经有病历信息了
            return;
        }
        if(!PayStatusEnum.PAID.getValue().equals(register.getPayStatus())){
            throw new BusinessFailException("状态不允许");
        }
        ClinicMedicalDTO clinicMedical = new ClinicMedicalDTO();
        BeanUtils.copyProperties(register,clinicMedical);
        //默认增加 主诉 + 现病史 + 既往史（患者）+过敏史（患者）+体格检查+诊断
        clinicMedical.setFieldList(getDefaultFieldList(register.getPatientId()));
        clinicMedical.setCreateUserId(register.getPatientId());
        clinicMedical.setCreateBy(register.getPatientName());
        addMedicalDTO(clinicMedical, ReqSourceEnum.ADMIN.getValue());
    }

    /**
     * 获取默认的病历字段
     * @param patientId
     * @return
     */
    public List<MedicalFieldDetail> getDefaultFieldList(Long patientId) {
        List<MedicalField> medicalList = medicalFieldService.getDefaultFieldList();
        if(CollectionUtils.isEmpty(medicalList)){
            return null;
        }
        ClinicPatient patient = patientService.getPatientById(patientId);
        if(patient == null){
            return null;
        }
        List<MedicalFieldDetail> medicalFieldDetailList = new ArrayList<>();
        for(MedicalField medicalField : medicalList){
            MedicalFieldDetail medicalFieldDetail = new MedicalFieldDetail();
            BeanUtils.copyProperties(medicalField,medicalFieldDetail);
            if(MedicalConstant.GMS.equals(medicalField.getFieldCode())){
                //过敏史获取患者的
                medicalFieldDetail.setFieldValue(patient.getAllergyHistory());
            }else if (MedicalConstant.JWS.equals(medicalField.getFieldCode())){
                //既往史获取患者的
                medicalFieldDetail.setFieldValue(patient.getMedicalHistory());
            }
            medicalFieldDetailList.add(medicalFieldDetail);
        }
        return medicalFieldDetailList;
    }

    /**
     * 添加病历
     * @param clinicMedicalDTO
     */
    @Transactional(rollbackFor = Exception.class)
    public Long addMedicalDTO(ClinicMedicalDTO clinicMedicalDTO,String reqSource) {
        validateMedicalDTO(clinicMedicalDTO,OperateTypeEnum.ADD.getValue(),reqSource);
        clinicMedicalDTO.setVisitStatus(VisitStatusEnum.WAITING.getValue());
        clinicMedicalDTO.setIsDelete(YesOrNoEnum.NO.getValue());
        clinicMedicalDTO.setIsEnabled(YesOrNoEnum.YES.getValue());
        clinicMedicalDTO.setCreateTime(new Date());
        clinicMedicalMapper.insertSelective(clinicMedicalDTO);
        addMedicalDetailBatch(
                clinicMedicalDTO.getClinicId(),
                clinicMedicalDTO.getMedicalId(),
                clinicMedicalDTO.getCreateUserId(),
                clinicMedicalDTO.getCreateBy(),
                clinicMedicalDTO.getExamList(),
                clinicMedicalDTO.getFieldList(),
                clinicMedicalDTO.getRxList()
        );
        return clinicMedicalDTO.getMedicalId();
    }

    /**
     * 批量添加门诊信息
     * @param clinicId
     * @param medicalId
     * @param createUserId
     * @param createBy
     * @param examList
     * @param fieldList
     * @param rxList
     */
    @Transactional(rollbackFor = Exception.class)
    public void addMedicalDetailBatch(Long clinicId, Long medicalId,
                                      Long createUserId,
                                      String createBy,
                                      List<ExamDetail> examList,
                                      List<MedicalFieldDetail> fieldList,
                                      List<RxBase> rxList) {
        Date createTime = new Date();
        //保存病历字段
        addFieldDetailList(clinicId,medicalId,createUserId,createBy,createTime, fieldList);
        //保存查验项目
        addClinicExamDetailBatch(clinicId,medicalId,createUserId,createBy,createTime,examList);
        //保存处方项目
        addClinicMedicalRxBatch(clinicId, medicalId, createUserId, createBy, createTime, rxList);
    }

    /**
     * 批量添加处方
     * @param clinicId
     * @param templateId
     * @param createUserId
     * @param createBy
     * @param createTime
     * @param rxList
     */
    @Transactional(rollbackFor = Exception.class)
    public void addClinicMedicalRxBatch(Long clinicId, Long templateId, Long createUserId, String createBy, Date createTime, List<RxBase> rxList) {
        if(CollectionUtils.isEmpty(rxList)){
            return;
        }
        List<ClinicMedicalRx> clinicMedicalRxList = new ArrayList<>();
        for (RxBase rxBase : rxList) {
            ClinicMedicalRx clinicMedicalRx = new ClinicMedicalRx();
            BeanUtils.copyProperties(rxBase,clinicMedicalRx);
            clinicMedicalRx.setMedicalId(templateId);
            clinicMedicalRx.setPayStatus(PayStatusEnum.ORDERED.getValue());
            clinicMedicalRx.setClinicId(clinicId);
            clinicMedicalRx.setIsEnabled(YesOrNoEnum.YES.getValue());
            clinicMedicalRx.setIsDelete(YesOrNoEnum.NO.getValue());
            clinicMedicalRx.setCreateUserId(createUserId);
            clinicMedicalRx.setCreateBy(createBy);
            clinicMedicalRx.setCreateTime(createTime);
            if(StringUtil.isBlank(clinicMedicalRx.getRxJson())){
                // 根据 rxType 类型添加到对应的列表中
                if (RxTypeEnum.DRUG.getValue().equals(rxBase.getRxType())) {
                    RxDrug rxDrug = (RxDrug) rxBase;
                    clinicMedicalRx.setRxJson(JsonUtil.obj2Json(rxDrug.getDetailList()));
                } else if (RxTypeEnum.INFUSION.getValue().equals(rxBase.getRxType())) {
                    RxInfusion rxInfusion = (RxInfusion) rxBase;
                    clinicMedicalRx.setRxJson(JsonUtil.obj2Json(rxInfusion.getGroupList()));
                } else if (RxTypeEnum.EXT.getValue().equals(rxBase.getRxType())) {
                    RxExt rxExt = (RxExt) rxBase;
                    clinicMedicalRx.setRxJson(JsonUtil.obj2Json(rxExt.getExtInfo()));
                } else if (RxTypeEnum.TCM.getValue().equals(rxBase.getRxType())) {
                    RxTcm rxTcm = (RxTcm) rxBase;
                    clinicMedicalRx.setRxJson(JsonUtil.obj2Json(rxTcm.getTcmInfo()));
                }
            }
            clinicMedicalRxList.add(clinicMedicalRx);
        }
        specClinicMedicalMapper.addMedicalRxBatch(clinicMedicalRxList);
    }

    /**
     * 批量添加
     * @param clinicId
     * @param medicalId
     * @param createUserId
     * @param createBy
     * @param createTime
     * @param detailList
     */
    @Transactional(rollbackFor = Exception.class)
    public void addClinicExamDetailBatch(Long clinicId, Long medicalId, Long createUserId, String createBy, Date createTime, List<ExamDetail> detailList) {
        if(CollectionUtils.isEmpty(detailList)){
            return;
        }
        List<ClinicMedicalExam> examList = new ArrayList<>();
        for(ExamDetail examDetail : detailList){
            ClinicMedicalExam clinicMedicalExam = new ClinicMedicalExam();
            BeanUtils.copyProperties(examDetail,clinicMedicalExam);
            clinicMedicalExam.setMedicalId(medicalId);
            clinicMedicalExam.setPayStatus(PayStatusEnum.ORDERED.getValue());
            clinicMedicalExam.setClinicId(clinicId);
            clinicMedicalExam.setIsEnabled(YesOrNoEnum.YES.getValue());
            clinicMedicalExam.setIsDelete(YesOrNoEnum.NO.getValue());
            clinicMedicalExam.setCreateUserId(createUserId);
            clinicMedicalExam.setCreateBy(createBy);
            clinicMedicalExam.setCreateTime(createTime);
            examList.add(clinicMedicalExam);
        }
        specClinicMedicalMapper.addMedicalExamBatch(examList);
    }

    /**
     * 保存病历模板字段详情
     * @param clinicId
     * @param medicalId
     * @param createUserId
     * @param createBy
     * @param createTime
     * @param detailList
     */
    @Transactional(rollbackFor = Exception.class)
    public void addFieldDetailList(Long clinicId, Long medicalId, Long createUserId, String createBy, Date createTime,List<MedicalFieldDetail> detailList) {
        ClinicMedicalField clinicMedicalField = new ClinicMedicalField();
        clinicMedicalField.setMedicalId(medicalId);
        clinicMedicalField.setFieldListJson(JsonUtil.obj2Json(detailList));
        clinicMedicalField.setClinicId(clinicId);
        clinicMedicalField.setCreateUserId(createUserId);
        clinicMedicalField.setCreateBy(createBy);
        clinicMedicalField.setCreateTime(createTime);
        medicalFieldInsertSelective(clinicMedicalField);
    }

    /**
     * 保存模板病历字段
     * @param clinicMedicalField
     */
    @Transactional(rollbackFor = Exception.class)
    public void medicalFieldInsertSelective(ClinicMedicalField clinicMedicalField){
        clinicMedicalField.setIsEnabled(YesOrNoEnum.YES.getValue());
        clinicMedicalField.setIsDelete(YesOrNoEnum.NO.getValue());
        clinicMedicalField.setCreateTime(new Date());
        clinicMedicalFieldMapper.insertSelective(clinicMedicalField);
    }


    /**
     * 修改病历
     * @param clinicMedicalDTO
     */
    @Transactional(rollbackFor = Exception.class)
    public Long updateMedicalDTO(ClinicMedicalDTO clinicMedicalDTO) {
        //参数校验
        validateMedicalDTO(clinicMedicalDTO,OperateTypeEnum.EDIT.getValue(),ReqSourceEnum.WEB.getValue());
        ClinicMedical clinicMedical = getMedicalById(clinicMedicalDTO.getMedicalId());
        if(clinicMedical == null){
            throw new BusinessFailException("病历不存在");
        }
        clinicMedicalDTO.setUpdateTime(new Date());
        clinicMedicalMapper.updateByPrimaryKeySelective(clinicMedicalDTO);
        updateMedicalDetailBatch(
                clinicMedicalDTO.getClinicId(),
                clinicMedicalDTO.getMedicalId(),
                clinicMedicalDTO.getUpdateUserId(),
                clinicMedicalDTO.getUpdateBy(),
                clinicMedicalDTO.getFieldList(),
                clinicMedicalDTO.getExamList(),
                clinicMedicalDTO.getRxList()
        );
        return clinicMedicalDTO.getMedicalId();
    }

    /**
     *
     * @param clinicId
     * @param medicalId
     * @param updateUserId
     * @param updateBy
     * @param fieldList
     * @param examList
     * @param rxList
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateMedicalDetailBatch(Long clinicId, Long medicalId, Long updateUserId, String updateBy, List<MedicalFieldDetail> fieldList, List<ExamDetail> examList, List<RxBase> rxList) {
        Date updateTime = new Date();
        //批量修改病历
        updateFieldDetailList(medicalId,updateUserId,updateBy,updateTime,fieldList);
        //修改查验项目
        updateExamDetailList(clinicId,medicalId,updateUserId,updateBy,updateTime,examList);
        //修改处方项目
        updateRxDetailList(clinicId,medicalId,updateUserId,updateBy,updateTime,rxList);
    }

    /**
     * 修改病历处方
     * @param clinicId
     * @param medicalId
     * @param updateUserId
     * @param updateBy
     * @param updateTime
     * @param rxList
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateRxDetailList(Long clinicId, Long medicalId, Long updateUserId, String updateBy, Date updateTime, List<RxBase> rxList) {
        //如果处方的ID为空代表新增
        List<RxBase> insertRxList = rxList.stream()
                .filter(rxBase -> StringUtil.isBlank(rxBase.getRxId()))
                .collect(Collectors.toList());
        //需要修改的处方=修改+删除
        List<ClinicMedicalRx> updateRxList = getAllUpdateRxList(clinicId,medicalId,updateUserId,updateBy,updateTime,rxList);
        if(!CollectionUtils.isEmpty(insertRxList)){
            //保存处方
            addClinicMedicalRxBatch(clinicId,medicalId,updateUserId,updateBy,updateTime,insertRxList);
        }
        if(!CollectionUtils.isEmpty(updateRxList)){
            //修改处方
            specClinicMedicalMapper.updateMedicalRxBatch(updateRxList);
        }
    }

    /**
     * 获取所有要修改的处方=update+delete
     * @param clinicId
     * @param medicalId
     * @param updateUserId
     * @param updateBy
     * @param updateTime
     * @param rxList
     * @return
     */
    public List<ClinicMedicalRx> getAllUpdateRxList(Long clinicId, Long medicalId, Long updateUserId, String updateBy, Date updateTime, List<RxBase> rxList) {
        //全部修改的项目
        List<ClinicMedicalRx> allUpdateRxList = new ArrayList<>();
        // 查询已有的项目
        List<ClinicMedicalRx> dbRxList = getRxListByMedicalId(clinicId, medicalId);
        //删除的项目
        List<ClinicMedicalRx> deletedRxList = getDeletedRxList(dbRxList,rxList);
        if(!CollectionUtils.isEmpty(deletedRxList)){
            List<Long> deletedRxId = new ArrayList<>();
            for(ClinicMedicalRx deleteRx : deletedRxList){
                if(PayStatusEnum.PAID.getValue().equals(deleteRx.getPayStatus())){
                    throw new BusinessFailException(deleteRx.getRxName()+"已支付不允许删除！");
                }
                deletedRxId.add(deleteRx.getRxId());
                deleteRx.setIsDelete(YesOrNoEnum.YES.getValue());
                deleteRx.setUpdateUserId(updateUserId);
                deleteRx.setUpdateBy(updateBy);
                deleteRx.setUpdateTime(updateTime);
            }
            allUpdateRxList.addAll(deletedRxList);
        }
        //要修改的项目
        List<ClinicMedicalRx> updatedRxList = getUpdatedRxList(dbRxList,deletedRxList);
        if(!CollectionUtils.isEmpty(updatedRxList)){
            for(ClinicMedicalRx clinicMedicalRx : updatedRxList){
                if(PayStatusEnum.PAID.getValue().equals(clinicMedicalRx.getPayStatus())){
                    //已支付的项目不修改
                    continue;
                }
                RxBase inputRx = rxList.stream()
                        .filter(rxBase -> rxBase.getRxId() != null && rxBase.getRxId().equals(clinicMedicalRx.getRxId())) // 根据 rxId 过滤
                        .findFirst() // 获取第一个匹配的 RxBase
                        .orElse(null); // 如果没有匹配的元素，则返回 null
                if(inputRx == null){
                    continue;
                }
                clinicMedicalRx.setStorageId(inputRx.getStorageId());
                clinicMedicalRx.setTotalAmount(inputRx.getTotalAmount());
                // 根据 rxType 类型添加到对应的列表中
                if (RxTypeEnum.DRUG.getValue().equals(inputRx.getRxType())) {
                    RxDrug rxDrug = (RxDrug) inputRx;
                    clinicMedicalRx.setRxJson(JsonUtil.obj2Json(rxDrug.getDetailList()));
                } else if (RxTypeEnum.INFUSION.getValue().equals(inputRx.getRxType())) {
                    RxInfusion rxInfusion = (RxInfusion) inputRx;
                    clinicMedicalRx.setRxJson(JsonUtil.obj2Json(rxInfusion.getGroupList()));
                } else if (RxTypeEnum.EXT.getValue().equals(inputRx.getRxType())) {
                    RxExt rxExt = (RxExt) inputRx;
                    clinicMedicalRx.setRxJson(JsonUtil.obj2Json(rxExt.getExtInfo()));
                } else if (RxTypeEnum.TCM.getValue().equals(inputRx.getRxType())) {
                    RxTcm rxTcm = (RxTcm) inputRx;
                    clinicMedicalRx.setRxJson(JsonUtil.obj2Json(rxTcm.getTcmInfo()));
                }
                clinicMedicalRx.setUpdateUserId(updateUserId);
                clinicMedicalRx.setUpdateBy(updateBy);
                clinicMedicalRx.setUpdateTime(updateTime);
                allUpdateRxList.add(clinicMedicalRx);
            }
        }
        return allUpdateRxList;

    }

    /**
     * 修改的处方= 数据库中的处方-删除的处方
     * @param dbRxList
     * @param deletedRxList
     * @return
     */
    public List<ClinicMedicalRx> getUpdatedRxList(List<ClinicMedicalRx> dbRxList, List<ClinicMedicalRx> deletedRxList) {
        if(CollectionUtils.isEmpty(dbRxList)){
            return null;
        }
        // 提取 dbRxList 中的 rxId
        List<Long> dbRxIds = dbRxList.stream()
                .map(ClinicMedicalRx::getRxId)  // 提取 rxId 字段
                .collect(Collectors.toList());
        if(!CollectionUtils.isEmpty(deletedRxList)){
            // 提取 deletedRxList 中的 rxId
            List<Long> deletedRxIds = deletedRxList.stream()
                    .map(ClinicMedicalRx::getRxId)  // 提取 rxId 字段
                    .collect(Collectors.toList());

            // 求差集（dbRxIds - deletedRxIds）
            dbRxIds.removeAll(deletedRxIds);
        }
        if(CollectionUtils.isEmpty(dbRxIds)){
            return null;
        }
        // 使用差集的 rxId 从 dbRxList 中提取需要修改的项目
        List<ClinicMedicalRx> modifiedRxList = dbRxList.stream()
                .filter(item -> dbRxIds.contains(item.getRxId()))  // 保留差集中的 rxId
                .collect(Collectors.toList());
        return modifiedRxList;
    }

    /**
     * 删除的处方=数据库的处方-rxList中没有的处方
     * @param dbRxList
     * @param rxList
     * @return
     */
    public List<ClinicMedicalRx> getDeletedRxList(List<ClinicMedicalRx> dbRxList, List<RxBase> rxList) {
        if(CollectionUtils.isEmpty(dbRxList)){
            return null;
        }
        // 获取 dbExamList 中有但 examList 中没有的项目
        Set<Long> rxIdsFromDb = dbRxList.stream()
                .map(ClinicMedicalRx::getRxId) // 提取 dbExamList 中的 examId
                .collect(Collectors.toSet());

        Set<Long> rxIdsFromInput = rxList.stream()
                .filter(rxBase -> !StringUtil.isBlank(rxBase.getRxId())) // 过滤掉 examId 为 null 的项
                .map(RxBase::getRxId)  // 提取 examList 中的 examId
                .collect(Collectors.toSet());  // 将结果收集到 Set 中

        if(!CollectionUtils.isEmpty(rxIdsFromInput)){
            // 计算 dbExamList 中的项目在 examList 中不存在的那些
            rxIdsFromDb.removeAll(rxIdsFromInput); // 移除在 examList 中存在的 examId
        }
        if(CollectionUtils.isEmpty(rxIdsFromDb)){
            return null;
        }
        // 根据剩下的 examId 获取 dbExamList 中对应的项目
        return dbRxList.stream()
                .filter(medicalRx -> rxIdsFromDb.contains(medicalRx.getRxId())) // 只保留那些需要删除的项目
                .collect(Collectors.toList());
    }

    /**
     * 根据病历获取处方
     * @param clinicId
     * @param medicalId
     * @return
     */
    public List<ClinicMedicalRx> getRxListByMedicalId(Long clinicId, Long medicalId) {
        ClinicMedicalRxExample example = new ClinicMedicalRxExample();
        ClinicMedicalRxExample.Criteria criteria = example.createCriteria();
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        criteria.andClinicIdEqualTo(clinicId);
        criteria.andMedicalIdEqualTo(medicalId);
        return clinicMedicalRxMapper.selectByExample(example);
    }

    /**
     * 修改查验项目
     * @param clinicId
     * @param medicalId
     * @param updateBy
     * @param updateTime
     * @param examList
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateExamDetailList(Long clinicId, Long medicalId, Long updateUserId,String updateBy, Date updateTime, List<ExamDetail> examList) {
        //需要保存的
        List<ExamDetail> insertExamList = examList.stream()
                .filter(examDetail -> StringUtil.isBlank(examDetail.getExamId()))
                .collect(Collectors.toList());
        //需要修改的包括删除的
        List<ClinicMedicalExam> updateExamList = getAllUpdateExamList(clinicId,medicalId,updateUserId,updateBy,updateTime,examList);
        if(!CollectionUtils.isEmpty(insertExamList)){
            //保存查验项目
            addClinicExamDetailBatch(clinicId,medicalId,updateUserId,updateBy,updateTime,insertExamList);
        }
        if(!CollectionUtils.isEmpty(updateExamList)){
            specClinicMedicalMapper.updateMedicalExamBatch(updateExamList);
        }
    }

    /**
     * 获取修改的集合
     * @param clinicId
     * @param medicalId
     * @param updateUserId
     * @param updateBy
     * @param updateTime
     * @param examList
     * @return
     */
    public List<ClinicMedicalExam> getAllUpdateExamList(Long clinicId, Long medicalId, Long updateUserId, String updateBy, Date updateTime, List<ExamDetail> examList) {
        //全部修改的项目
        List<ClinicMedicalExam> allUpdateExamList = new ArrayList<>();
        // 查询已有的项目
        List<ClinicMedicalExam> dbExamList = getExamListByMedicalId(clinicId, medicalId);
        //删除的项目
        List<ClinicMedicalExam> deletedExamList = getDeletedExamList(dbExamList,examList);
        if(!CollectionUtils.isEmpty(deletedExamList)){
            for(ClinicMedicalExam deletedExam : deletedExamList){
                if(PayStatusEnum.PAID.getValue().equals(deletedExam.getPayStatus())){
                    throw new BusinessFailException(deletedExam.getProjectName()+"已支付不允许删除！");
                }
                deletedExam.setIsDelete(YesOrNoEnum.YES.getValue());
                deletedExam.setUpdateUserId(updateUserId);
                deletedExam.setUpdateBy(updateBy);
                deletedExam.setUpdateTime(updateTime);
            }
            allUpdateExamList.addAll(deletedExamList);
        }
        //获取修改的项目
        List<ClinicMedicalExam> updateExamList = getUpdatedExamList(dbExamList,deletedExamList);
        if(!CollectionUtils.isEmpty(updateExamList)){
            for(ClinicMedicalExam clinicMedicalExam : updateExamList){
                if(PayStatusEnum.PAID.getValue().equals(clinicMedicalExam.getPayStatus())){
                    //已支付的项目不修改
                    continue;
                }
                ExamDetail inputExam = examList.stream()
                        .filter(examDetail -> examDetail.getExamId() != null
                                && examDetail.getExamId().equals(clinicMedicalExam.getExamId())) // // 根据 rxId 过滤 先判空再比较
                        .findFirst() // 获取第一个匹配的 RxBase
                        .orElse(null);// 如果没有匹配的元素，则返回 null
                if(inputExam == null){
                    continue;
                }
                clinicMedicalExam.setSubtotal(inputExam.getSubtotal());
                clinicMedicalExam.setProjectId(inputExam.getProjectId());
                clinicMedicalExam.setProjectName(inputExam.getProjectName());
                clinicMedicalExam.setProjectCategory(inputExam.getProjectCategory());
                clinicMedicalExam.setProjectType(inputExam.getProjectType());
                clinicMedicalExam.setPrice(inputExam.getPrice());
                clinicMedicalExam.setFrequencyCode(inputExam.getFrequencyCode());
                clinicMedicalExam.setCycle(inputExam.getCycle());
                clinicMedicalExam.setCycleUnit(inputExam.getCycleUnit());
                clinicMedicalExam.setRemark(inputExam.getRemark());
                clinicMedicalExam.setTotalOutQty(inputExam.getTotalOutQty());
                clinicMedicalExam.setTotalOutQtyUnit(inputExam.getTotalOutQtyUnit());
                clinicMedicalExam.setUpdateUserId(updateUserId);
                clinicMedicalExam.setUpdateBy(updateBy);
                clinicMedicalExam.setUpdateTime(updateTime);
                allUpdateExamList.add(clinicMedicalExam);
            }
        }
        return allUpdateExamList;
    }

    /**
     * 修改的处方= 数据库中的处方-删除的处方
     * @param dbExamList
     * @param deletedExamList
     * @return
     */
    public List<ClinicMedicalExam> getUpdatedExamList(List<ClinicMedicalExam> dbExamList, List<ClinicMedicalExam> deletedExamList) {
        if(CollectionUtils.isEmpty(dbExamList)){
            return null;
        }
        // 提取 dbRxList 中的 rxId
        List<Long> dbExamIds = dbExamList.stream()
                .map(ClinicMedicalExam::getExamId)  // 提取 rxId 字段
                .collect(Collectors.toList());
        if(!CollectionUtils.isEmpty(deletedExamList)){
            // 提取 deletedRxList 中的 rxId
            List<Long> deletedExamIds = deletedExamList.stream()
                    .map(ClinicMedicalExam::getExamId)  // 提取 rxId 字段
                    .collect(Collectors.toList());

            // 求差集（dbRxIds - deletedRxIds）
            dbExamIds.removeAll(deletedExamIds);
        }
        if(CollectionUtils.isEmpty(dbExamIds)){
            return null;
        }
        // 使用差集的 rxId 从 dbRxList 中提取需要修改的项目
        List<ClinicMedicalExam> modifiedRxList = dbExamList.stream()
                .filter(item -> dbExamIds.contains(item.getExamId()))  // 保留差集中的 rxId
                .collect(Collectors.toList());
        return modifiedRxList;
    }


    public List<ClinicMedicalExam> getDeletedExamList(List<ClinicMedicalExam> dbExamList, List<ExamDetail> examList) {
        if(CollectionUtils.isEmpty(dbExamList)){
            return null;
        }
        // 获取 dbExamList 中有但 examList 中没有的项目
        Set<Long> examIdsFromDb = dbExamList.stream()
                .map(ClinicMedicalExam::getExamId) // 提取 dbExamList 中的 examId
                .collect(Collectors.toSet());

        Set<Long> examIdsFromInput = examList.stream()
                .filter(exam -> !StringUtil.isBlank(exam.getExamId())) // 过滤掉 examId 为 null 的项
                .map(ExamDetail::getExamId)  // 提取 examList 中的 examId
                .collect(Collectors.toSet());  // 将结果收集到 Set 中

        if(!CollectionUtils.isEmpty(examIdsFromInput)){
            // 计算 dbExamList 中的项目在 examList 中不存在的那些
            examIdsFromDb.removeAll(examIdsFromInput); // 移除在 examList 中存在的 examId
        }
        if(CollectionUtils.isEmpty(examIdsFromDb)){
            return null;
        }
        // 根据剩下的 examId 获取 dbExamList 中对应的项目
        return dbExamList.stream()
                .filter(examDetail -> examIdsFromDb.contains(examDetail.getExamId())) // 只保留那些需要删除的项目
                .collect(Collectors.toList());
    }

    public List<ClinicMedicalExam> getExamListByMedicalId(Long clinicId, Long medicalId) {
        ClinicMedicalExamExample example = new ClinicMedicalExamExample();
        ClinicMedicalExamExample.Criteria criteria = example.createCriteria();
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        criteria.andClinicIdEqualTo(clinicId);
        criteria.andMedicalIdEqualTo(medicalId);
        return clinicMedicalExamMapper.selectByExample(example);
    }


    /**
     * 修改病历字段
     * @param medicalId
     * @param updateUserId
     * @param updateBy
     * @param detailList
     */
    public void updateFieldDetailList(Long medicalId, Long updateUserId, String updateBy, Date updateTime,List<MedicalFieldDetail> detailList) {
        ClinicMedicalField clinicMedicalField = new ClinicMedicalField();
        clinicMedicalField.setMedicalId(medicalId);
        clinicMedicalField.setFieldListJson(JsonUtil.obj2Json(detailList));
        clinicMedicalField.setUpdateUserId(updateUserId);
        clinicMedicalField.setUpdateBy(updateBy);
        clinicMedicalField.setUpdateTime(updateTime);
        clinicMedicalFieldMapper.updateByPrimaryKeySelective(clinicMedicalField);
    }


    /**
     * 校验病历字段
     * @param clinicMedicalDTO
     * @param reqSource
     */
    public void validateMedicalDTO(ClinicMedicalDTO clinicMedicalDTO,String operateType,String reqSource) {
        //校验患者信息
        ClinicPatient patientInfo = new ClinicPatient();
        BeanUtils.copyProperties(clinicMedicalDTO,patientInfo);
        patientService.validatePatient(patientInfo);
        if(OperateTypeEnum.ADD.getValue().equals(operateType) && ReqSourceEnum.WEB.getValue().equals(reqSource)){
            //门诊直接看诊
            if(clinicMedicalDTO.getPatientId() == null){
                ClinicPatient dbPatientInfo = patientService.addPatient(patientInfo);
                clinicMedicalDTO.setPatientId(dbPatientInfo.getPatientId());
                if(clinicMedicalDTO.getSolarBirthday() == null){
                    clinicMedicalDTO.setSolarBirthday(dbPatientInfo.getSolarBirthday());
                }
                if(clinicMedicalDTO.getLunarBirthday() == null){
                    clinicMedicalDTO.setLunarBirthday(dbPatientInfo.getLunarBirthday());
                }
                if(StringUtil.isBlank(clinicMedicalDTO.getAgeYear())){
                    clinicMedicalDTO.setAgeYear(dbPatientInfo.getAgeYear());
                }
                if(StringUtil.isBlank(clinicMedicalDTO.getAgeMonth())){
                    clinicMedicalDTO.setAgeMonth(dbPatientInfo.getAgeMonth());
                }
            }
            //门诊直接看诊需要挂一个号
            ClinicRegister clinicRegister = new ClinicRegister();
            clinicRegister.setVisitDate(LocalDate.now());
            clinicRegister.setVisitPeriod(VisitPeriodEnum.getPeriod(LocalTime.now()));
            clinicRegister.setDoctorId(clinicMedicalDTO.getDoctorId());
            clinicRegister.setDoctorName(clinicMedicalDTO.getDoctorName());
            clinicRegister.setRegMethod(RegMethodEnum.REGISTER_ONSITE.getValue());
            clinicRegister.setRegChannel(RegChannelEnum.OUTPATIENT.getValue());
            clinicRegister.setVisitType(VisitTypeEnum.FIRST_VISIT.getValue());
            //直接看诊的默认都是急诊
            clinicRegister.setRegType(RegTypeEnum.EMERGENCY.getValue());
            clinicRegister.setPatientId(clinicMedicalDTO.getPatientId());
            clinicRegister.setPatientName(clinicMedicalDTO.getPatientName());
            clinicRegister.setPatientGender(clinicMedicalDTO.getPatientGender());
            clinicRegister.setPatientPhone(clinicMedicalDTO.getPatientPhone());
            clinicRegister.setAgeYear(clinicMedicalDTO.getAgeYear());
            clinicRegister.setAgeMonth(clinicMedicalDTO.getAgeMonth());
            clinicRegister.setWeight(clinicMedicalDTO.getWeight());
            clinicRegister.setSystolicBp(clinicMedicalDTO.getSystolicBp());
            clinicRegister.setDiastolicBp(clinicMedicalDTO.getDiastolicBp());
            clinicRegister.setClinicId(clinicMedicalDTO.getClinicId());
            clinicRegister.setCreateUserId(clinicMedicalDTO.getCreateUserId());
            clinicRegister.setCreateBy(clinicMedicalDTO.getCreateBy());
            clinicRegister = registerService.addRegister(clinicRegister);
            clinicMedicalDTO.setRegisterId(clinicRegister.getRegisterId());
            clinicMedicalDTO.setVisitNo(clinicRegister.getVisitNo());
            clinicMedicalDTO.setVisitDate(clinicRegister.getVisitDate());
            clinicMedicalDTO.setVisitPeriod(clinicRegister.getVisitPeriod());
            clinicMedicalDTO.setVisitType(clinicRegister.getVisitType());
            clinicMedicalDTO.setRegType(clinicRegister.getRegType());
            clinicMedicalDTO.setVisitSeqNo(clinicRegister.getVisitSeqNo());
            clinicMedicalDTO.setVisitShiftId(clinicRegister.getVisitShiftId());
            clinicMedicalDTO.setVisitStartTime(clinicRegister.getVisitStartTime());
            clinicMedicalDTO.setVisitEndTime(clinicRegister.getVisitEndTime());
            clinicMedicalDTO.setDeptId(clinicRegister.getDeptId());
            clinicMedicalDTO.setDeptName(clinicRegister.getDeptName());
            clinicMedicalDTO.setRoomId(clinicRegister.getRoomId());
            clinicMedicalDTO.setRoomName(clinicRegister.getRoomName());
        }
        if(StringUtil.isBlank(clinicMedicalDTO.getVisitStatus())){
            clinicMedicalDTO.setVisitStatus(VisitStatusEnum.WAITING.getValue());
        }
        if(StringUtil.isBlank(clinicMedicalDTO.getIsFollowUp())){
            clinicMedicalDTO.setIsFollowUp(YesOrNoEnum.NO.getValue());
        }
        if(YesOrNoEnum.YES.getValue().equals(clinicMedicalDTO.getIsFollowUp())){
            //如果是随访
            if(clinicMedicalDTO.getFollowUpDays() <= CommonConstant.DEFAULT_0){
                throw new BusinessFailException("随访时间必须大于"+ CommonConstant.DEFAULT_0+"天");
            }
        }
        if(StringUtil.isBlank(clinicMedicalDTO.getSortNum())){
            clinicMedicalDTO.setSortNum(CommonConstant.DEFAULT_1);
        }
        if(YesOrNoEnum.YES.getValue().equals(clinicMedicalDTO.getIsFollowUp())){
            if(StringUtil.isBlank(clinicMedicalDTO.getFollowUpDays())){
                clinicMedicalDTO.setFollowUpDays(CommonConstant.DEFAULT_3);
            }
        }
        if(OperateTypeEnum.ADD.getValue().equals(operateType) && ReqSourceEnum.ADMIN.getValue().equals(reqSource)){
            //系统自动增加的病历没有处方和项目
            return;
        }
        //病历字段校验
        validateMedicalField(YesOrNoEnum.YES.getValue(),operateType,clinicMedicalDTO.getFieldList());
        //检查项目校验
        if(!CollectionUtils.isEmpty(clinicMedicalDTO.getExamList())){
            validateMedicalExam(YesOrNoEnum.YES.getValue(),clinicMedicalDTO.getExamList());
        }
        //处方校验
        if(!CollectionUtils.isEmpty(clinicMedicalDTO.getRxList())){
            validateMedicalRx(YesOrNoEnum.YES.getValue(),clinicMedicalDTO.getClinicId(),clinicMedicalDTO.getRxList());
        }
    }


    /**
     * 分页查询门诊信息
     * @param name 模糊搜索名称（可根据具体字段修改）
     * @param pageNo 页码
     * @param pageSize 每页数量
     * @return 分页结果
     */
    public PageInfo<ClinicMedical> getMedicalListByCondition(String name, Integer pageNo, Integer pageSize) {
        ClinicMedicalExample example = new ClinicMedicalExample();
        ClinicMedicalExample.Criteria criteria = example.createCriteria();
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        Long totalCount = clinicMedicalMapper.countByExample(example);
        if (totalCount == null || totalCount == 0) {
            return PageInfo.build();
        }

        example.setOffset(PageUtils.getOffset(pageNo, pageSize));
        example.setLimit(pageSize);
        example.setOrderByClause("create_time desc");
        List<ClinicMedical> medicalList = clinicMedicalMapper.selectByExample(example);
        return new PageInfo<>(totalCount, medicalList);
    }

    /**
     * 添加门诊信息
     * @param clinicMedical 实体对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void addMedical(ClinicMedical clinicMedical) {
        validateMedical(clinicMedical);
        clinicMedical.setIsDelete(YesOrNoEnum.NO.getValue());
        clinicMedical.setIsEnabled(YesOrNoEnum.YES.getValue());
        clinicMedical.setCreateTime(new Date());
        clinicMedicalMapper.insertSelective(clinicMedical);
    }

    /**
     * 校验门诊信息实体
     * @param clinicMedical 实体对象
     */
    public void validateMedical(ClinicMedical clinicMedical) {

    }

    /**
     * 根据主键查询门诊信息
     * @param medicalId 主键ID
     * @return 查询结果
     */
    public ClinicMedical getMedicalById(Long medicalId) {
        if (StringUtil.isBlank(medicalId)) {
            return null;
        }
        ClinicMedical clinicMedical = clinicMedicalMapper.selectByPrimaryKey(medicalId);
        if (clinicMedical == null || YesOrNoEnum.YES.getValue().equals(clinicMedical.getIsDelete())) {
            return null;
        }
        return clinicMedical;
    }

    /**
     * 修改门诊信息
     * @param clinicMedical 实体对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateMedical(ClinicMedical clinicMedical) {
        ClinicMedical dbMedical = getMedicalById(clinicMedical.getMedicalId());
        if (dbMedical == null) {
            throw new BusinessFailException("门诊信息不存在");
        }
        clinicMedical.setUpdateTime(new Date());
        clinicMedicalMapper.updateByPrimaryKeySelective(clinicMedical);
    }


    /**
     * 删除门诊信息（逻辑删除）
     * @param clinicMedical 实体对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteMedical(ClinicMedical clinicMedical) {
        ClinicMedical dbMedical = getMedicalById(clinicMedical.getMedicalId());
        if (dbMedical == null) {
            throw new BusinessFailException("门诊信息不存在");
        }
        dbMedical.setIsDelete(YesOrNoEnum.YES.getValue());
        dbMedical.setUpdateUserId(clinicMedical.getUpdateUserId());
        dbMedical.setUpdateBy(clinicMedical.getUpdateBy());
        dbMedical.setUpdateTime(new Date());
        clinicMedicalMapper.updateByPrimaryKeySelective(dbMedical);
    }

    /**
     * 启用门诊信息
     * @param clinicMedical 实体对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void enableMedical(ClinicMedical clinicMedical) {
        ClinicMedical dbMedical = getMedicalById(clinicMedical.getMedicalId());
        if (dbMedical == null) {
            throw new BusinessFailException("门诊信息不存在");
        }
        if (YesOrNoEnum.YES.getValue().equals(dbMedical.getIsEnabled())) {
            return;
        }
        dbMedical.setIsEnabled(YesOrNoEnum.YES.getValue());
        dbMedical.setUpdateUserId(clinicMedical.getUpdateUserId());
        dbMedical.setUpdateBy(clinicMedical.getUpdateBy());
        dbMedical.setUpdateTime(new Date());
        clinicMedicalMapper.updateByPrimaryKeySelective(dbMedical);
    }

    /**
     * 停用门诊信息
     * @param clinicMedical 实体对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void disableMedical(ClinicMedical clinicMedical) {
        ClinicMedical dbMedical = getMedicalById(clinicMedical.getMedicalId());
        if (dbMedical == null) {
            throw new BusinessFailException("门诊信息不存在");
        }
        if (YesOrNoEnum.NO.getValue().equals(dbMedical.getIsEnabled())) {
            return;
        }
        dbMedical.setIsEnabled(YesOrNoEnum.NO.getValue());
        dbMedical.setUpdateUserId(clinicMedical.getUpdateUserId());
        dbMedical.setUpdateBy(clinicMedical.getUpdateBy());
        dbMedical.setUpdateTime(new Date());
        clinicMedicalMapper.updateByPrimaryKeySelective(dbMedical);
    }

    /**
     * 修改检查支付状态
     * @param examIdList
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateExamListPayStatus(List<Long> examIdList) {
        ClinicMedicalExamExample example = new ClinicMedicalExamExample();
        ClinicMedicalExamExample.Criteria criteria = example.createCriteria();
        criteria.andExamIdIn(examIdList);
        ClinicMedicalExam detail = new ClinicMedicalExam();
        detail.setPayStatus(PayStatusEnum.PAID.getValue());
        detail.setPayTime(new Date());
        clinicMedicalExamMapper.updateByExampleSelective(detail,example);
    }

    /**
     * 修改处方单支付状态
     * @param rxIdList
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateRxListPayStatus(List<Long> rxIdList) {
        ClinicMedicalRxExample example = new ClinicMedicalRxExample();
        ClinicMedicalRxExample.Criteria criteria = example.createCriteria();
        criteria.andRxIdIn(rxIdList);
        ClinicMedicalRx detail = new ClinicMedicalRx();
        detail.setPayStatus(PayStatusEnum.PAID.getValue());
        detail.setPayTime(new Date());
        clinicMedicalRxMapper.updateByExampleSelective(detail,example);
    }

}
